import { _decorator, Component, Node, log } from 'cc';
const { ccclass } = _decorator;
import { AxingManager } from './AxingManager';
import { Vec2, Vec3 } from 'cc';

@ccclass('Test')
export class Test extends Component {
  private axingManager: AxingManager;

  start() {
    this.axingManager = AxingManager.getInstance();
  }

  public onTestButtonClick() {
    this.testAStar();
  }

  public onTestButtonClick2() {
    // 延迟一帧执行测试，确保场景已经完全加载
    this.scheduleOnce(() => {
      this.testMassivePathfinding();
    }, 0);
  }

  public findPathDefault(start: Vec2, end: Vec2): void {
    this.axingManager.addPathFindingTask(start, end, (result: Vec3) => {
      console.log('Path found with default depth:', result);
    });
  }

  public findPathWithCustomDepth(start: Vec2, end: Vec2, depth: number): void {
    this.axingManager.addPathFindingTask(
      start,
      end,
      (result: Vec3) => {
        console.log('Path found with custom depth:', result);
      },
      depth
    );
  }

  public async testAStar(): Promise<void> {
    const mapWidth = 40; // 缩小地图尺寸，便于观察
    const mapHeight = 40;
    const mapData = new Array(mapWidth * mapHeight).fill(0);

    // 创建一个迷宫式的障碍布局
    // 横向墙
    for (let x = 10; x < 30; x++) {
      mapData[x + mapWidth * 10] = 1; // 上墙
      mapData[x + mapWidth * 30] = 1; // 下墙
    }
    // 竖向墙
    for (let y = 10; y < 31; y++) {
      mapData[10 + mapWidth * y] = 1; // 左墙
      mapData[30 + mapWidth * y] = 1; // 右墙
    }
    // 在墙上开几个口
    mapData[20 + mapWidth * 10] = 0; // 上墙开口
    mapData[30 + mapWidth * 20] = 0; // 右墙开口
    mapData[20 + mapWidth * 30] = 0; // 下墙开口
    mapData[10 + mapWidth * 20] = 0; // 左墙开口

    this.axingManager.initMapData_zhangaiwu(mapWidth, mapHeight, mapData);

    const testCases = [
      {
        start: new Vec2(5, 5),
        end: new Vec2(35, 35),
        desc: '穿过迷宫的对角线寻路测试',
      },
      {
        start: new Vec2(5, 20),
        end: new Vec2(35, 20),
        desc: '横向穿过迷宫测试',
      },
      {
        start: new Vec2(20, 5),
        end: new Vec2(20, 35),
        desc: '竖向穿过迷宫测试',
      },
    ];

    log('=== 开始A*寻路测试 ===');
    for (const test of testCases) {
      log(`\n测试场景: ${test.desc}`);
      log(`起点: (${test.start.x}, ${test.start.y})`);
      log(`终点: (${test.end.x}, ${test.end.y})`);

      try {
        // 只测试一个合适的深度
        const result = await this.testWithDepth(
          test.start,
          test.end,
          1000,
          '寻路测试'
        );

        // 打印更大范围的地图视图
        this.printPartialMap(mapWidth, mapHeight, test.start, test.end, 40);
      } catch (error) {
        log(`测试出错: ${error}`);
      }
    }
    log('\n=== A*寻路测试完成 ===');
  }

  private async testWithDepth(
    start: Vec2,
    end: Vec2,
    depth: number,
    depthDesc: string
  ): Promise<void> {
    const startTime = Date.now();
    const result = await new Promise<Vec3>((resolve) => {
      this.axingManager.addPathFindingTask(start, end, resolve, depth);
    });
    const endTime = Date.now();

    log(`\n${depthDesc}测试结果:`);
    log(`耗时: ${endTime - startTime}ms`);
    if (result.equals(Vec3.ZERO)) {
      log('未找到路径');
    } else {
      log(`找到路径，移动向量: (${result.x}, ${result.y}, ${result.z})`);
    }
  }

  private printPartialMap(
    width: number,
    height: number,
    start: Vec2,
    end: Vec2,
    radius: number = 20
  ): void {
    log('\n当前地图状态:');
    log('S: 起点  E: 终点  █: 障碍物  ·: 可通行区域');

    const minY = Math.max(0, Math.min(start.y, end.y) - radius);
    const maxY = Math.min(height, Math.max(start.y, end.y) + radius);
    const minX = Math.max(0, Math.min(start.x, end.x) - radius);
    const maxX = Math.min(width, Math.max(start.x, end.x) + radius);

    let mapStr = '    '; // 添加列号的空间
    // 打印列号
    for (let x = minX; x < maxX; x++) {
      mapStr += this.padLeft((x % 10).toString(), 2, ' ');
    }
    mapStr += '\n';

    for (let y = minY; y < maxY; y++) {
      mapStr += this.padLeft(y.toString(), 3, ' ') + ' '; // 添加行号
      for (let x = minX; x < maxX; x++) {
        if (x === Math.floor(start.x) && y === Math.floor(start.y)) {
          mapStr += 'S ';
        } else if (x === Math.floor(end.x) && y === Math.floor(end.y)) {
          mapStr += 'E ';
        } else {
          mapStr += this.axingManager.map2d.data[y][x] === 0 ? '· ' : '█ ';
        }
      }
      mapStr += '\n';
    }
    log(mapStr);
  }

  // 添加一个辅助方法来替代 padStart
  private padLeft(str: string, length: number, char: string): string {
    while (str.length < length) {
      str = char + str;
    }
    return str;
  }

  public async testMassivePathfinding(): Promise<void> {
    // 设置是否使用分帧队列
    this.axingManager.setUseFrameQueue(false);

    // 初始化地图
    const mapWidth = 200;
    const mapHeight = 200;
    const mapData = new Array(mapWidth * mapHeight).fill(0);

    // 添加障碍物
    for (let i = 50; i < 150; i++) {
      mapData[i + mapWidth * 100] = 1; // 横墙
    }
    for (let i = 50; i < 150; i++) {
      mapData[100 + mapWidth * i] = 1; // 竖墙
    }

    this.axingManager.initMapData_zhangaiwu(mapWidth, mapHeight, mapData);

    // 创建大量寻路请求
    const requestCount = 1000; // 同时发起1000个寻路请求
    const requests: Promise<void>[] = [];
    const startTime = Date.now();

    log(`=== 开始大规模寻路测试 (${requestCount}个请求) ===`);

    // 统计变量
    let maxDepthReached = 0;
    let obstaclesCount = 0;

    // 创建随机的寻路请求
    for (let i = 0; i < requestCount; i++) {
      const start = new Vec2(
        Math.floor(Math.random() * mapWidth),
        Math.floor(Math.random() * mapHeight)
      );
      const end = new Vec2(
        Math.floor(Math.random() * mapWidth),
        Math.floor(Math.random() * mapHeight)
      );

      // 检查起点和终点是否是障碍物
      if (
        !this.axingManager.isValidPoint(start) ||
        !this.axingManager.isValidPoint(end)
      ) {
        obstaclesCount++;
      }

      const promise = new Promise<void>((resolve) => {
        this.axingManager.addPathFindingTask(
          start,
          end,
          (result: Vec3) => {
            if (result.equals(Vec3.ZERO)) {
              maxDepthReached++;
            }
            resolve();
          },
          500 // 使用固定深度
        );
      });

      requests.push(promise);

      // 每添加100个请求输出一次进度
      if ((i + 1) % 100 === 0) {
        log(`已添加 ${i + 1} 个寻路请求...`);
      }
    }

    // 等待所有请求完成
    try {
      await Promise.all(requests);
      const endTime = Date.now();
      const totalTime = endTime - startTime;
      const averageTime = totalTime / requestCount;

      log('\n=== 大规模寻路测试完成 ===');
      log(`总耗时: ${totalTime}ms`);
      log(`平均每个请求耗时: ${averageTime.toFixed(2)}ms`);
      log(`每秒处理请求数: ${(1000 / averageTime).toFixed(2)}`);
      log(`达到最大深度的请求数: ${maxDepthReached}`);
      log(`起点或终点是障碍物的请求数: ${obstaclesCount}`);
    } catch (error) {
      log('测试过程中出现错误:', error);
    }
  }
}
